#pragma once
#include<glad/glad.h>
#include<string>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

#define SHADER_TO_STRING(s) #s

#define MATH_PI 3.1415926535897932384626433832802

class OpenGLUtils
{
public:
	OpenGLUtils();
	~OpenGLUtils();
	static GLuint LoadShader(GLenum shardType, const char *pSource);

	static GLuint CreateProgram(const char *pVertexShaderSource, const char *pFragShaderSource,
		GLuint &vertexShaderHandle, GLuint &fragShaderHandle);
	static GLuint CreateProgram(const char *pVertexShaderSource, const char *pFragShaderSource);

	static GLuint CreateProgramWithFeedback(
		const char *pVertexShaderSource,
		const char *pFragShaderSource,
		GLuint &vertexShaderHandle,
		GLuint &fragShaderHandle,
		const GLchar **varying,
		int varyingCount);

	static void DeleteProgram(GLuint &program);

	static void CheckGLError(const char *pGLOperation);
	static void setBool(GLuint programId, const std::string &name, bool value) {
		glUniform1i(glGetUniformLocation(programId, name.c_str()), (int)value);
	}

	static void setInt(GLuint programId, const std::string &name, int value) {
		glUniform1i(glGetUniformLocation(programId, name.c_str()), value);
	}

	static void setFloat(GLuint programId, const std::string &name, float value) {
		glUniform1f(glGetUniformLocation(programId, name.c_str()), value);
	}

	

	static void setVec2(GLuint programId, const std::string &name, float x, float y) {
		glUniform2f(glGetUniformLocation(programId, name.c_str()), x, y);
	}

	

	static void setVec3(GLuint programId, const std::string &name, float x, float y, float z) {
		glUniform3f(glGetUniformLocation(programId, name.c_str()), x, y, z);
	}

	

	static void setVec4(GLuint programId, const std::string &name, float x, float y, float z, float w) {
		glUniform4f(glGetUniformLocation(programId, name.c_str()), x, y, z, w);
	}

	
	void matToTexture(GLuint& textureId, const Mat& mat); 
	//static glm::vec3 texCoordToVertexCoord(glm::vec2 &texCoord) {
	//	return glm::vec3(2 * texCoord.x - 1, 1 - 2 * texCoord.y, 0);
	//}
};

